home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-01
/
ohlcpio.zip
/
COPYPASS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-02
|
9KB
|
295 lines
/* copypass.c - cpio copy pass sub-function.
Copyright (C) 1988, 1989, 1990 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef S_IFLNK
#define lstat stat
#endif
#include <errno.h>
extern int errno;
#include <fcntl.h>
#include <sys/file.h>
#ifdef USG
#include <time.h>
#include <string.h>
#else
#include <sys/time.h>
#include <strings.h>
#endif
#include "cpio.h"
#include "dstring.h"
#include "extern.h"
/* Copy files listed on the standard input into directory `directory_name'.
If `link_flag', link instead of copying. */
void
process_copy_pass ()
{
dynamic_string input_name; /* Name of file from stdin. */
dynamic_string output_name; /* Name of new file. */
int dirname_len; /* Length of `directory_name'. */
int res; /* Result of functions. */
char *slash; /* For moving past slashes in input name. */
long times[2]; /* For resetting file times after copy. */
struct stat in_file_stat; /* Stat record for input file. */
struct stat out_file_stat; /* Stat record for output file. */
int in_file_des; /* Input file descriptor. */
int out_file_des; /* Output file descriptor. */
/* Initialize the copy out. */
dirname_len = strlen (directory_name);
ds_init (&input_name, 128);
ds_init (&output_name, dirname_len + 2);
strcpy (output_name.ds_string, directory_name);
output_name.ds_string[dirname_len] = '/';
output_is_seekable = TRUE;
/* Copy files with names read from stdin. */
while (ds_fgets (stdin, &input_name) != NULL)
{
char *link_name = NULL;
/* Check for blank line and ignore it if found. */
if (input_name.ds_string[0] == '\0')
{
error (0, 0, "blank line ignored");
continue;
}
if ((*xstat) (input_name.ds_string, &in_file_stat) < 0)
{
error (0, errno, "%s", input_name.ds_string);
continue;
}
/* Make the name of the new file. */
for (slash = input_name.ds_string; *slash == '/'; ++slash)
;
ds_resize (&output_name, dirname_len + strlen (slash) + 2);
strcpy (output_name.ds_string + dirname_len + 1, slash);
if (lstat (output_name.ds_string, &out_file_stat) == 0)
{
if (!unconditional_flag
&& in_file_stat.st_mtime < out_file_stat.st_mtime)
{
error (0, 0, "%s not created: newer version exists",
output_name.ds_string);
continue; /* Go to the next file. */
}
else if ((out_file_stat.st_mode & S_IFMT) == S_IFDIR)
{
error (0, 0, "cannot remove current %s: Is a directory",
output_name.ds_string);
continue; /* Go to the next file. */
}
else if (unlink (output_name.ds_string))
{
error (0, errno, "cannot remove current %s",
output_name.ds_string);
continue; /* Go to the next file. */
}
}
/* Do the real copy or link. */
switch (in_file_stat.st_mode & S_IFMT)
{
case S_IFREG:
/* Can the current file be linked to a another file?
Set link_name to the original file name. */
if (link_flag)
{
/* User said to link it if possible. */
link_name = input_name.ds_string;
}
else if (in_file_stat.st_nlink > 1)
{
/* Is the file a link to a previously copied file? */
link_name = find_inode_file (in_file_stat.st_ino);
if (link_name == NULL)
add_inode (in_file_stat.st_ino, output_name.ds_string);
}
/* If there is a link name, do the link. */
if (link_name != NULL)
{
res = link (link_name, output_name.ds_string);
if (res < 0 && create_dir_flag)
{
create_all_directories (output_name.ds_string);
res = link (link_name, output_name.ds_string);
}
if (res == 0)
{
if (verbose_flag)
error (0, 0, "%s linked to %s",
link_name, output_name.ds_string);
}
else if (link_flag)
{
error (0, errno, "cannot link %s to %s",
link_name, output_name.ds_string);
}
else
{
/* For some reason we can not link a previously linked file.
Do a complete copy. */
link_name = NULL;
}
}
/* If the file was not linked, copy contents of file. */
if (link_name == NULL)
{
in_file_des = open (input_name.ds_string, O_RDONLY, 0);
if (in_file_des < 0)
{
error (0, errno, "%s", input_name.ds_string);
continue;
}
out_file_des = open (output_name.ds_string,
O_CREAT | O_WRONLY, 0600);
if (out_file_des < 0 && create_dir_flag)
{
create_all_directories (output_name.ds_string);
out_file_des = open (output_name.ds_string,
O_CREAT | O_WRONLY, 0600);
}
if (out_file_des < 0)
{
error (0, errno, "%s", output_name.ds_string);
close (in_file_des);
continue;
}
copy_files (in_file_des, out_file_des, in_file_stat.st_size);
empty_output_buffer (out_file_des);
finish_output_file (output_name.ds_string, out_file_des);
close (in_file_des);
close (out_file_des);
/* Set the attributes of the new file. */
if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0)
error (0, errno, "%s", output_name.ds_string);
if (chown (output_name.ds_string, in_file_stat.st_uid,
in_file_stat.st_gid) < 0
&& errno != EPERM)
error (0, errno, "%s", output_name.ds_string);
if (reset_time_flag)
{
times[0] = in_file_stat.st_atime;
times[1] = in_file_stat.st_mtime;
if (utime (input_name.ds_string, times) < 0)
error (0, errno, "%s", input_name.ds_string);
if (utime (output_name.ds_string, times) < 0)
error (0, errno, "%s", output_name.ds_string);
}
}
break;
case S_IFDIR:
res = mkdir (output_name.ds_string, in_file_stat.st_mode);
if (res < 0 && create_dir_flag)
{
create_all_directories (output_name.ds_string);
res = mkdir (output_name.ds_string, in_file_stat.st_mode);
}
if (res < 0)
{
error (0, errno, "%s", output_name.ds_string);
continue;
}
if (chown (output_name.ds_string, in_file_stat.st_uid,
in_file_stat.st_gid) < 0
&& errno != EPERM)
error (0, errno, "%s", output_name.ds_string);
break;
case S_IFCHR:
case S_IFBLK:
#ifdef S_IFIFO
case S_IFIFO:
#endif
#ifdef S_IFSOCK
case S_IFSOCK:
#endif
res = mknod (output_name.ds_string, in_file_stat.st_mode,
in_file_stat.st_rdev);
if (res < 0 && create_dir_flag)
{
create_all_directories (output_name.ds_string);
res = mknod (output_name.ds_string, in_file_stat.st_mode,
in_file_stat.st_rdev);
}
if (res < 0)
{
error (0, errno, "%s", output_name.ds_string);
continue;
}
if (chown (output_name.ds_string, in_file_stat.st_uid,
in_file_stat.st_gid) < 0
&& errno != EPERM)
error (0, errno, "%s", output_name.ds_string);
break;
#ifdef S_IFLNK
case S_IFLNK:
link_name = (char *) xmalloc (in_file_stat.st_size + 1);
if (readlink (input_name.ds_string, link_name,
in_file_stat.st_size) < 0)
{
error (0, errno, "%s", input_name.ds_string);
free (link_name);
continue;
}
link_name[in_file_stat.st_size] = '\0';
res = symlink (link_name, output_name.ds_string);
if (res < 0 && create_dir_flag)
{
create_all_directories (output_name.ds_string);
res = symlink (link_name, output_name.ds_string);
}
if (res < 0)
{
error (0, errno, "%s", output_name.ds_string);
free (link_name);
continue;
}
free (link_name);
break;
#endif
default:
error (0, 0, "%s: unknown file type", input_name.ds_string);
}
if (verbose_flag)
fprintf (stderr, "%s\n", output_name.ds_string);
}
res = output_bytes / io_block_size;
if (res == 1)
fprintf (stderr, "1 block\n");
else
fprintf (stderr, "%d blocks\n", res);
}